package com.my.lucky.controller;

import cn.hutool.core.collection.ListUtil;
import com.my.lucky.model.Stock;
import com.my.lucky.service.Selector;
import com.my.lucky.service.SohuStockAPI;
import com.my.lucky.service.StockDataLoader;
import com.my.lucky.service.TradeSignal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;

@Slf4j
@Controller
public class StockController {
    private static final int DAYS = 20;
    private static final int TOP_N = 5;
    private static List<String> selected;
    private final ConcurrentSkipListMap<String, Map<String, Object>> stockCache = new ConcurrentSkipListMap<>();
    @Autowired
    StockDataLoader loader;
    private String currentPicker = "default";

    @GetMapping("/")
    public String index(Model model) {
        try {
            List<Map<String, Object>> stocks = new ArrayList<>(stockCache.values());
            if (stocks.isEmpty()) {
                // 如果缓存为空，立即更新数据
                //   updateStockData();
                //   stocks = new ArrayList<>(stockCache.values());
                model.addAttribute("error", "数据加载中...");
            } else {
                // 为每个股票添加技术指标
                for (Map<String, Object> stock : stocks) {
                    String code = (String) stock.get("code");
                    List<Stock> stockHistory = loader.getStockHistory(code);
                    if (stockHistory != null && !stockHistory.isEmpty()) {
                        // 计算技术指标
                        double rsi = calculateRSI(stockHistory);
                        double ma5 = calculateMA(stockHistory, 5);
                        double ma20 = calculateMA(stockHistory, 20);

                        stock.put("rsi", String.format("%.2f", rsi));
                        stock.put("ma5", String.format("%.2f", ma5));
                        stock.put("ma20", String.format("%.2f", ma20));

                        // 计算买卖信号
                        boolean isBuy = TradeSignal.isBuySignal(stockHistory);
                        boolean isSell = TradeSignal.isSellSignal(stockHistory);
                        stock.put("buySignal", isBuy);
                        stock.put("sellSignal", isSell);
                    } else {
                        // 如果没有历史数据，设置默认值
                        stock.put("rsi", "-");
                        stock.put("ma5", "-");
                        stock.put("ma20", "-");
                        stock.put("buySignal", false);
                        stock.put("sellSignal", false);
                    }
                }
                model.addAttribute("stocks", stocks);
            }
        } catch (Exception e) {
            e.printStackTrace();
            model.addAttribute("error", "获取数据失败：" + e.getMessage());
        }
        return "index";
    }

    @GetMapping("/re")
    @ResponseBody
    public List<Map<String, Object>> re(@RequestParam(defaultValue = "default") String picker,
                                        @RequestParam(defaultValue = "false") boolean gemOnly) {
        List<Map<String, Object>> stocks = new ArrayList<>(stockCache.values());
        if (gemOnly) {
            stocks.removeIf(stock -> !((String) stock.get("code")).contains("300"));
        }
        return stocks;
    }

//    @PostConstruct
//    void init() {
//        Map<String, List<Stock>> last30DaysStockData = loader.getLast30DaysStockData(false);
//        selected = Selector.select(currentPicker, last30DaysStockData, TOP_N);
//    }

    @GetMapping("/refresh")
    @ResponseBody
    public List<Map<String, Object>> refresh(@RequestParam(defaultValue = "default") String picker,
                                             @RequestParam(defaultValue = "false") boolean gemOnly) {
        this.currentPicker = picker;
        Map<String, List<Stock>> last30DaysStockData = loader.getLast30DaysStockData(gemOnly);
        log.info("当前选择器: {}", currentPicker);
        selected = Selector.select(currentPicker, last30DaysStockData, TOP_N);
        if (gemOnly) {
            selected.removeIf(code -> !code.contains("300"));
        }
        log.info("选中数量: {}", selected.size());
        stockCache.clear();
        updateStockData();
        return new ArrayList<>(stockCache.values());
    }

    //   @Scheduled(fixedDelay = 1000)
    public void updateStockData() {
        try {
            if (selected == null || selected.size() == 0) {
                return;
            }

            for (String code : selected) {
                try {
                    Map<String, String> quote = SohuStockAPI.getRealtimeQuote(code);
                    double price = Double.parseDouble(quote.get("price"));
                    double preClose = Double.parseDouble(quote.get("pre_close"));
                    double changePercent = (price - preClose) / preClose * 100;
                    Map<String, Object> stockInfo = new HashMap<>();
                    stockInfo.put("code", code);
                    stockInfo.put("name", quote.get("name"));
                    stockInfo.put("price", String.format("%.2f", price));
                    stockInfo.put("changePercent", String.format("%.2f", changePercent));
                    stockInfo.put("open", quote.get("open"));
                    stockInfo.put("high", quote.get("high"));
                    stockInfo.put("low", quote.get("low"));

                    // 获取历史数据进行买卖信号判断
                    List<Stock> stockHistory = loader.getStockHistory(code);
                    if (stockHistory != null && !stockHistory.isEmpty()) {
                        // 创建新的 Stock 对象并添加到历史数据中
                        Stock latestStock = new Stock(
                                code,
                                LocalDate.now().toString(),
                                Double.parseDouble(quote.get("price")),
                                Double.parseDouble(quote.get("open")),
                                Double.parseDouble(quote.get("high")),
                                Double.parseDouble(quote.get("low")),
                                Double.parseDouble(quote.get("volume"))
                        );
                        stockHistory.add(latestStock);

                        // 计算技术指标
                        double rsi = calculateRSI(stockHistory);
                        double ma5 = calculateMA(stockHistory, 5);
                        double ma20 = calculateMA(stockHistory, 20);

                        stockInfo.put("rsi", String.format("%.2f", rsi));
                        stockInfo.put("ma5", String.format("%.2f", ma5));
                        stockInfo.put("ma20", String.format("%.2f", ma20));

                        // 计算买卖信号
                        boolean isBuy = TradeSignal.isBuySignal(stockHistory);
                        boolean isSell = TradeSignal.isSellSignal(stockHistory);
                        stockInfo.put("buySignal", isBuy);
                        stockInfo.put("sellSignal", isSell);
                    } else {
                        // 如果没有历史数据，设置默认值
                        stockInfo.put("rsi", "-");
                        stockInfo.put("ma5", "-");
                        stockInfo.put("ma20", "-");
                        stockInfo.put("buySignal", false);
                        stockInfo.put("sellSignal", false);
                    }

                    stockCache.put(code, stockInfo);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @GetMapping("/search")
    @ResponseBody
    public List<Map<String, Object>> search(@RequestParam String code,
                                            @RequestParam(defaultValue = "false") boolean gemOnly) {
        List<Map<String, Object>> result = new ArrayList<>();
        try {
            // 确保代码格式正确
            if (!code.startsWith("cn_")) {
                if (code.startsWith("6")) {
                    code = "cn_" + code;
                } else if (code.startsWith("0") || code.startsWith("3")) {
                    code = "cn_" + code;
                } else {
                    return result;
                }
            }

            // 获取股票实时数据
            Map<String, String> quote = SohuStockAPI.getRealtimeQuote(code);
            if (quote != null) {
                double price = Double.parseDouble(quote.get("price"));
                double preClose = Double.parseDouble(quote.get("pre_close"));
                double changePercent = (price - preClose) / preClose * 100;

                Map<String, Object> stockInfo = new HashMap<>();
                stockInfo.put("code", code);
                stockInfo.put("name", quote.get("name"));
                stockInfo.put("price", String.format("%.2f", price));
                stockInfo.put("changePercent", String.format("%.2f", changePercent));
                stockInfo.put("open", quote.get("open"));
                stockInfo.put("high", quote.get("high"));
                stockInfo.put("low", quote.get("low"));

                // 获取历史数据进行买卖信号判断
                List<Stock> stockHistory = loader.getStockHistory(code);
                if (stockHistory != null && !stockHistory.isEmpty()) {
                    // 创建新的 Stock 对象并添加到历史数据中
                    Stock latestStock = new Stock(
                            code,
                            LocalDate.now().toString(),
                            Double.parseDouble(quote.get("price")),
                            Double.parseDouble(quote.get("open")),
                            Double.parseDouble(quote.get("high")),
                            Double.parseDouble(quote.get("low")),
                            Double.parseDouble(quote.get("volume"))
                            // 实时数据可能没有成交量信息
                    );
                    stockHistory.add(latestStock);

                    boolean isBuy = TradeSignal.isBuySignal(stockHistory);
                    boolean isSell = TradeSignal.isSellSignal(stockHistory);
                    stockInfo.put("buySignal", isBuy);
                    stockInfo.put("sellSignal", isSell);

                    // 计算技术指标
                    double rsi = calculateRSI(stockHistory);
                    double ma5 = calculateMA(stockHistory, 5);
                    double ma20 = calculateMA(stockHistory, 20);

                    stockInfo.put("rsi", String.format("%.2f", rsi));
                    stockInfo.put("ma5", String.format("%.2f", ma5));
                    stockInfo.put("ma20", String.format("%.2f", ma20));
                }

                stockCache.clear();
                selected = ListUtil.toList(code);
                stockCache.put(code, stockInfo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>(stockCache.values());
    }

    // 计算RSI
    private double calculateRSI(List<Stock> stockHistory) {
        int period = 14;
        if (stockHistory.size() < period + 1) {
            return 50.0;
        }

        double sumGain = 0.0;
        double sumLoss = 0.0;

        for (int i = stockHistory.size() - period; i < stockHistory.size(); i++) {
            double change = stockHistory.get(i).getClose() - stockHistory.get(i - 1).getClose();
            if (change > 0) {
                sumGain += change;
            } else {
                sumLoss -= change;
            }
        }

        if (sumLoss == 0) {
            return 100.0;
        }

        double rs = sumGain / sumLoss;
        return 100.0 - (100.0 / (1 + rs));
    }

    // 计算移动平均线
    private double calculateMA(List<Stock> stockHistory, int period) {
        if (stockHistory.size() < period) {
            return 0.0;
        }

        double sum = 0.0;
        for (int i = stockHistory.size() - period; i < stockHistory.size(); i++) {
            sum += stockHistory.get(i).getClose();
        }
        return sum / period;
    }
}